package com.qtrue.thread;

/**
 * @Package: com.qtrue.thread
 * @ClassName: WindowTest04
 * @Author: xiaoBao
 * @CreateTime: 2022-05-08 18:47
 * @Description:使用“同步方法”解决实现Runnable接口的线程安全问题
 *
 *  关于同步方法的总结：
 *      1. 同步方法仍然涉及到线程同步锁，只是不需要我们显式的声明。
 *      2. 非静态的同步方法，线程同步监视器是：this（当前类对象）
 *      3. 静态的同步方法，线程同步监视器是：当前类的本身（className.class）
 */
public class WindowTest04 {
    public static void main(String[] args) {
        // 创建实现类的对象
        Window3 window = new Window3();

        // 将实现类对象作为参数传递到Thread类的构造器中
        Thread thread01 = new Thread(window);
        Thread thread02 = new Thread(window);
        Thread thread03 = new Thread(window);
        Thread thread04 = new Thread(window);

        // 设置线程名称
        thread01.setName("窗口一");
        thread02.setName("窗口二");
        thread03.setName("窗口三");
        thread04.setName("窗口四");

        // 启动线程
        thread01.start();
        thread02.start();
        thread03.start();
        thread04.start();
    }
}

class Window3 implements Runnable {
    // 总票数
    private int ticket = 100;
//    Object obj = new Object(); // 声明一个对象作为同步监视器

    @Override
    public void run() {

        while(true) {
            showMethod();
        }
    }

    // 同步方法（操作共享数据的代码）
    private synchronized void showMethod(){ // 在同步方法中，同步监视器为：this（当前类对象），在实现Runnable接口创建线程的方式下可行。
        if (ticket > 0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + "：卖票，票号为：" + ticket);

            ticket--;
        }
    }
}